home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
551-575
/
disk_562
/
intuisup
/
render
/
source.lzh
/
render.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-10-19
|
18KB
|
546 lines
/*************************************
* *
* Render v2.0 *
* by Torsten Jürgeleit in 05/91 *
* *
* Routines *
* *
*************************************/
/* Includes */
#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <functions.h>
#include "render.h"
/* Defines */
#define RED_SCALE 3 /* amount of RGB values to take in account the different visual impact of those colors */
#define GREEN_SCALE 6
#define BLUE_SCALE 2
/* Statics */
STATIC USHORT image_data_arrow_left[] = { /* bitmap data for left arrow image */
0x0780, 0x3e00, 0xf800, 0x3e00, 0x0780, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000
};
STATIC USHORT image_data_arrow_right[] = { /* bitmap data for right arrow image */
0xf000, 0x3e00, 0x0f80, 0x3e00, 0xf000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000
};
STATIC USHORT image_data_arrow_up[] = { /* bitmap data for up arrow image */
0x0800, 0x1c00, 0x3e00, 0x7700, 0xc180, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000
};
STATIC USHORT image_data_arrow_down[] = { /* bitmap data for down arrow image */
0xc180, 0x7700, 0x3e00, 0x1c00, 0x0800, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000
};
STATIC USHORT image_data_toggle_knob_unselected[] = { /* bitmap data for unselected toggle knob image */
0x1ffc, 0x0000, 0x7000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000,
0xc000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0x7000, 0x0000,
0x1000, 0x0000, /* Plane 0 */
0x0002, 0x0000, 0x0003, 0x8000, 0x0000, 0xc000, 0x0000, 0xc000,
0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0003, 0x8000,
0x0ffe, 0x0000 /* Plane 1 */
};
STATIC USHORT image_data_toggle_knob_selected[] = { /* bitmap data for selected toggle knob image */
0x0002, 0x0000, 0x0003, 0x8000, 0x03f0, 0xc000, 0x0ffc, 0xc000,
0x0ffc, 0xc000, 0x0ffc, 0xc000, 0x03f0, 0xc000, 0x0003, 0x8000,
0x0ffe, 0x0000, /* Plane 0 */
0x1ffc, 0x0000, 0x7000, 0x0000, 0xc3f0, 0x0000, 0xcffc, 0x0000,
0xcffc, 0x0000, 0xcffc, 0x0000, 0xc3f0, 0x0000, 0x7000, 0x0000,
0x1000, 0x0000 /* Plane 1 */
};
STATIC USHORT image_data_toggle_check_selected[] = { /* bitmap data for selected toggle checkmark image */
0x0038, 0x0060, 0x00c0, 0xe180, 0x7300, 0x3e00, 0x1c00
};
STATIC USHORT image_data_cycle[] = { /* bitmap data for cycle image */
0x7f01, 0xc181, 0xc181, 0xc7e1, 0xc3c1, 0xc181, 0xc001, 0xc181,
0x7f01, /* Plane 0 */
0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
0x0002 /* Plane 1 */
};
STATIC USHORT image_data_count_left[] = { /* bitmap data for left count image */
0x0700, 0x3f00, 0xff00, 0x3f00, 0x0700
};
STATIC USHORT image_data_count_right[] = { /* bitmap data for right count image */
0xe000, 0xfc00, 0xff00, 0xfc00, 0xe000
};
STATIC struct Image images[MAX_RENDER_IMAGES] = {
{ /* left arrow */
0, 0, IMAGE_ARROW_WIDTH, IMAGE_ARROW_HEIGHT, IMAGE_ARROW_DEPTH,
&image_data_arrow_left[0], 0, 0, NULL
}, { /* right arrow */
0, 0, IMAGE_ARROW_WIDTH, IMAGE_ARROW_HEIGHT, IMAGE_ARROW_DEPTH,
&image_data_arrow_right[0], 0, 0, NULL
}, { /* up arrow */
0, 0, IMAGE_ARROW_WIDTH, IMAGE_ARROW_HEIGHT, IMAGE_ARROW_DEPTH,
&image_data_arrow_up[0], 0, 0, NULL
}, { /* down arrow */
0, 0, IMAGE_ARROW_WIDTH, IMAGE_ARROW_HEIGHT, IMAGE_ARROW_DEPTH,
&image_data_arrow_down[0], 0, 0, NULL
}, { /* toggle select knob unselected */
0, 0, IMAGE_KNOB_WIDTH, IMAGE_KNOB_HEIGHT, IMAGE_KNOB_DEPTH,
&image_data_toggle_knob_unselected[0], 0, 0, NULL
}, { /* toggle select knob selected */
0, 0, IMAGE_KNOB_WIDTH, IMAGE_KNOB_HEIGHT, IMAGE_KNOB_DEPTH,
&image_data_toggle_knob_selected[0], 0, 0, NULL
}, { /* toggle select check unselected */
IMAGE_HORIZ_OFFSET, IMAGE_VERT_OFFSET, IMAGE_CHECK_WIDTH,
IMAGE_CHECK_HEIGHT, 0, NULL, 0, 0, NULL
}, { /* toggle select check selected */
IMAGE_HORIZ_OFFSET, IMAGE_VERT_OFFSET, IMAGE_CHECK_WIDTH,
IMAGE_CHECK_HEIGHT, IMAGE_CHECK_DEPTH,
&image_data_toggle_check_selected[0], 0, 0, NULL
}, { /* cycle */
0, 0, IMAGE_CYCLE_WIDTH, IMAGE_CYCLE_HEIGHT, IMAGE_CYCLE_DEPTH,
&image_data_cycle[0], 0, 0, NULL
}, { /* left count */
0, 0, IMAGE_COUNT_WIDTH, IMAGE_COUNT_HEIGHT, IMAGE_COUNT_DEPTH,
&image_data_count_left[0], 0, 0, NULL
}, { /* right count */
0, 0, IMAGE_COUNT_WIDTH, IMAGE_COUNT_HEIGHT, IMAGE_COUNT_DEPTH,
&image_data_count_right[0], 0, 0, NULL
}
};
STATIC struct TextAttr topaz80_attr = { (STRPTR)"topaz.font", TOPAZ_EIGHTY,
FS_NORMAL, FPF_ROMFONT };
/* Static prototypes */
SHORT calc_color_level(SHORT color);
VOID init_render_info_images(struct RenderInfo *ri);
UBYTE get_image_pixel_color(struct Image *image, USHORT x, USHORT y);
VOID set_image_pixel_color(struct Image *image, USHORT x, USHORT y,
UBYTE color);
/* Static pragmas */
#pragma regcall(calc_color_level(d0))
#pragma regcall(init_render_info_images(a0))
#pragma regcall(get_image_pixel_color(a0,d0,d1))
#pragma regcall(set_image_pixel_color(a0,d0,d1,d2))
/* Get render info for given screen */
struct RenderInfo *
get_render_info(struct Screen *screen, USHORT flags)
{
struct RenderInfo *ri = NULL;
struct Screen wb_screen;
struct ColorMap *cmap;
struct Image *image = &images[0];
USHORT *data;
ULONG data_size = 0;
SHORT i, j, temp, num_colors, back_color, colors[MAX_RENDER_COLORS],
color_levels[MAX_RENDER_COLORS], pens[MAX_RENDER_COLORS];
if (ri = AllocMem((LONG)sizeof(struct RenderInfo),
(LONG)MEMF_PUBLIC | MEMF_CLEAR)) {
/* If no screen given then use workbench screen */
if (! screen) {
GetScreenData((BYTE *)(screen = &wb_screen), (LONG)
sizeof(struct Screen), (LONG)WBENCHSCREEN,
(struct Screen *)NULL);
}
/* Get screen and window data */
ri->ri_ScreenWidth = screen->Width;
ri->ri_ScreenHeight = screen->Height;
ri->ri_ScreenDepth = screen->RastPort.BitMap->Depth;
ri->ri_WindowBorderTop = screen->BarHeight -
screen->BarVBorder + screen->WBorTop;
ri->ri_WindowBorderLeft = screen->WBorLeft;
ri->ri_WindowBorderRight = screen->WBorRight;
ri->ri_WindowBorderBottom = screen->WBorBottom;
ri->ri_Flags = flags;
/* Calc gadget chipmem data buffer size */
for (i = 0; i < MAX_RENDER_IMAGES; i++, image++) {
if (image->ImageData) {
data_size += (image->Width / 16 + (image->Width & 15 ? 1 : 0)) *
image->Height * ri->ri_ScreenDepth * 2;
}
}
if (!(data = AllocMem(data_size, (LONG)MEMF_PUBLIC | MEMF_CHIP |
MEMF_CLEAR))) {
FreeMem(ri, (LONG)sizeof(struct RenderInfo));
ri = NULL;
} else {
/* Insert image data buffer and size */
ri->ri_ImageData = data;
ri->ri_ImageDataSize = data_size;
/* Open screen text font and clone screen text attr struct */
Forbid();
if (screen->Font) {
ri->ri_TextFont = OpenFont(screen->Font);
}
Permit();
if (ri->ri_TextFont) {
ri->ri_TextAttr.ta_Name = (STRPTR)
ri->ri_TextFont->tf_Message.mn_Node.ln_Name;
ri->ri_TextAttr.ta_YSize = ri->ri_TextFont->tf_YSize;
ri->ri_TextAttr.ta_Style = ri->ri_TextFont->tf_Style;
ri->ri_TextAttr.ta_Flags = ri->ri_TextFont->tf_Flags;
} else {
ri->ri_TextFont = OpenFont(&topaz80_attr);
CopyMem((BYTE *)&topaz80_attr, (BYTE *)&ri->ri_TextAttr, (LONG)
sizeof(struct TextAttr));
}
/* Examine screen colors */
if ((num_colors = 1 << ri->ri_ScreenDepth) > MAX_RENDER_COLORS) {
num_colors = MAX_RENDER_COLORS;
}
if (num_colors < 3) {
/* Set render pens for monochrome screen */
ri->ri_HighlightPen = 1;
ri->ri_ShadowPen = 1;
ri->ri_TextPen1 = 1;
ri->ri_TextPen2 = 1;
ri->ri_BackPen = 0;
} else {
/* Get current screen colors */
Forbid();
cmap = screen->ViewPort.ColorMap;
for (i = 0; i < num_colors; i++) {
colors[i] = GetRGB4(cmap, (LONG)i);
color_levels[i] = calc_color_level(colors[i]);
pens[i] = i;
}
Permit();
/* Save normal background color */
back_color = colors[0];
/* Sort colors darkest to brightest (BUBBLE SORT) */
for (i = 0; i < (num_colors - 1); i++) {
for (j = i + 1; j < num_colors; j++) {
if (color_levels[i] > color_levels[j]) {
/* Swap colors, color levels and pens */
temp = colors[i];
colors[i] = colors[j];
colors[j] = temp;
temp = color_levels[i];
color_levels[i] = color_levels[j];
color_levels[j] = temp;
temp = pens[i];
pens[i] = pens[j];
pens[j] = temp;
}
}
}
if (flags & RENDER_INFO_FLAG_BACK_FILL) {
/* Set render pens - highlight pen first */
ri->ri_HighlightPen = pens[num_colors - 1];
/* Set shadow pen */
ri->ri_ShadowPen = pens[0];
/* Set back pen */
if (! pens[i = 1]) { /* don't use normal background color */
i++;
}
ri->ri_BackPen = pens[i];
back_color = colors[i]; /* new background color */
} else {
/* Set render pens - highlight pen first */
if (! pens[i = num_colors - 1]) { /* don't use normal background color */
i--;
}
ri->ri_HighlightPen = pens[i];
/* Set shadow pen */
if (! pens[i = 0]) {
i++;
}
ri->ri_ShadowPen = pens[i];
/* Set back pen */
ri->ri_BackPen = 0;
}
/* Set text pen 1 */
for (i = 0, j = 0; i < num_colors; i++) {
if ((temp = calc_color_difference(colors[i],
back_color)) > j) {
j = temp;
ri->ri_TextPen1 = pens[i];
}
}
/* Set text pen 2 */
for (i = 0, j = 0; i < num_colors; i++) {
if ((temp = calc_color_difference(colors[i],
back_color)) > j && pens[i] != ri->ri_TextPen1) {
j = temp;
ri->ri_TextPen2 = pens[i];
}
}
}
init_render_info_images(ri);
}
}
return(ri);
}
/* Calc color level with specified scaling values */
STATIC SHORT
calc_color_level(SHORT color)
{
return(calc_color_difference(color, 0));
}
/* Calc color difference with specified scaling values */
SHORT /* non static - needed by menus.c too */
calc_color_difference(SHORT color1, SHORT color2)
{
USHORT temp, diff;
temp = (color1 & 0x00f) - (color2 & 0x00f);
diff = temp * temp * BLUE_SCALE;
temp = ((color1 >> 4) & 0x00f) - ((color2 >> 4) & 0x00f);
diff += temp * temp * GREEN_SCALE;
temp = ((color1 >> 8) & 0x00f) - ((color2 >> 8) & 0x00f);
diff += temp * temp * RED_SCALE;
return(diff);
}
/* Init render info images */
STATIC VOID
init_render_info_images(struct RenderInfo *ri)
{
struct Image *image_src = &images[0], *image_dest = &ri->ri_Images[0];
UBYTE color;
USHORT i, x, y, *data = ri->ri_ImageData;
CopyMem((BYTE *)image_src, (BYTE *)image_dest, (LONG)(MAX_RENDER_IMAGES *
sizeof(struct Image)));
for (i = 0; i < MAX_RENDER_IMAGES; i++, image_src++, image_dest++) {
image_dest->Depth = ri->ri_ScreenDepth;
if (image_src->ImageData) {
/* Set data buffer ptr */
image_dest->ImageData = data;
image_dest->PlanePick = (1 << image_dest->Depth) - 1;
data += (image_dest->Width / 16 + (image_dest->Width & 15 ? 1 :
0)) * image_dest->Height * image_dest->Depth;
/* Convert image data */
for (y = 0; y < image_src->Height; y++) {
for (x = 0; x < image_src->Width; x++) {
switch(get_image_pixel_color(image_src, x, y)) {
case 0 : /* back pen */
color = ri->ri_BackPen;
break;
case 1 : /* highlight pen */
color = ri->ri_HighlightPen;
break;
case 2 : /* shadow pen */
color = ri->ri_ShadowPen;
break;
case 3 : /* special pen */
color = ri->ri_TextPen2;
break;
}
set_image_pixel_color(image_dest, x, y, color);
}
}
} else {
/* No image data -> monochrome rectangle */
switch(image_src->PlaneOnOff) {
case 0 : /* back pen */
color = ri->ri_BackPen;
break;
case 1 : /* highlight pen */
color = ri->ri_HighlightPen;
break;
case 2 : /* shadow pen */
color = ri->ri_ShadowPen;
break;
case 3 : /* special pen */
color = ri->ri_TextPen2;
break;
}
image_dest->PlaneOnOff = color;
}
}
}
/* Get color of image pixel */
STATIC UBYTE
get_image_pixel_color(struct Image *image, USHORT x, USHORT y)
{
UBYTE i, depth = image->Depth, color_mask = 1, color = 0;
USHORT modulo = image->Width / 16 + (image->Width & 15 ? 1 : 0),
*data = image->ImageData + y * modulo + x / 16,
bit_mask = 0x8000 >> (x & 15);
for (i = 0; i < depth; i++, data += image->Height * modulo,
color_mask <<= 1) {
if (*data & bit_mask) {
color |= color_mask;
}
}
return(color);
}
/* Set color of image pixel */
STATIC VOID
set_image_pixel_color(struct Image *image, USHORT x, USHORT y, UBYTE color)
{
UBYTE i, depth = image->Depth;
USHORT modulo = image->Width / 16 + (image->Width & 15 ? 1 : 0),
*data = image->ImageData + y * modulo + x / 16,
bit_mask = 0x8000 >> (x & 15);
for (i = 0; i < depth; i++, data += image->Height * modulo, color >>= 1) {
if (color & 1) {
*data |= bit_mask;
}
}
}
/* Free render info */
VOID
free_render_info(struct RenderInfo *ri)
{
if (ri) {
if (ri->ri_TextFont) {
CloseFont(ri->ri_TextFont);
}
FreeMem(ri->ri_ImageData, ri->ri_ImageDataSize);
FreeMem(ri, (LONG)sizeof(struct RenderInfo));
}
}
/* Open window */
struct Window *
open_window(struct RenderInfo *ri, struct NewWindow *org_nw, USHORT flags)
{
struct NewWindow *nw, new_nw;
struct Window *win = NULL;
if (ri && org_nw) {
/* Duplicate given new window struct */
CopyMem((BYTE *)org_nw, (BYTE *)(nw = &new_nw), (LONG)
sizeof(struct NewWindow));
/* Scale new window dimension */
if (nw->Width > ri->ri_ScreenWidth) {
nw->LeftEdge = 0;
nw->Width = ri->ri_ScreenWidth;
} else {
if ((nw->LeftEdge + nw->Width) > ri->ri_ScreenWidth) {
nw->LeftEdge = ri->ri_ScreenWidth - nw->Width;
}
}
if (nw->Height > ri->ri_ScreenHeight) {
nw->TopEdge = 0;
nw->Height = ri->ri_ScreenHeight;
} else {
if ((nw->TopEdge + nw->Height) > ri->ri_ScreenHeight) {
nw->TopEdge = ri->ri_ScreenHeight - nw->Height;
}
}
/* Change new window struct */
if (flags & OPEN_WINDOW_FLAG_CENTER_WINDOW) {
nw->LeftEdge = (ri->ri_ScreenWidth - nw->Width) / 2;
nw->TopEdge = (ri->ri_ScreenHeight - nw->Height) / 2;
}
if (flags & OPEN_WINDOW_FLAG_RENDER_PENS) {
if (ri->ri_Flags & RENDER_INFO_FLAG_BACK_FILL) {
nw->DetailPen = ri->ri_TextPen1;
nw->BlockPen = ri->ri_BackPen;
} else {
nw->DetailPen = ri->ri_BackPen;
nw->BlockPen = ri->ri_TextPen1;
}
}
if (ri->ri_Flags & RENDER_INFO_FLAG_INNER_WINDOW) {
nw->Width += ri->ri_WindowBorderLeft + ri->ri_WindowBorderRight;
if ((nw->LeftEdge + nw->Width) > ri->ri_ScreenWidth) {
nw->Width = ri->ri_ScreenWidth - nw->LeftEdge;
}
nw->Height += ri->ri_WindowBorderTop + ri->ri_WindowBorderBottom;
if ((nw->TopEdge + nw->Height) > ri->ri_ScreenHeight) {
nw->Height = ri->ri_ScreenHeight - nw->TopEdge;
}
}
if (win = OpenWindow(nw)) {
if (ri->ri_Flags & RENDER_INFO_FLAG_BACK_FILL) {
clear_render_window(ri, win, 0, 0, nw->Width, nw->Height);
}
}
}
return(win);
}
/* Clear given rectangle of window with data from render info */
VOID
clear_render_window(struct RenderInfo *ri, struct Window *win,
USHORT left_edge, USHORT top_edge, USHORT width, USHORT height)
{
struct RastPort *rp = win->RPort;
USHORT inner_left, inner_top, inner_width, inner_height, back_pen,
flags = ri->ri_Flags;
/* Calc inner window dimension */
if ((flags & RENDER_INFO_FLAG_INNER_WINDOW) ||
(flags & RENDER_INFO_FLAG_BACK_FILL)) {
inner_left = ri->ri_WindowBorderLeft;
inner_top = ri->ri_WindowBorderTop;
inner_width = win->Width - inner_left - ri->ri_WindowBorderRight;
inner_height = win->Height - inner_top - ri->ri_WindowBorderBottom;
} else {
inner_left = 0;
inner_top = 0;
inner_width = win->Width;
inner_height = win->Height;
}
/* Check if given rectangle fits into inner window and if not then scale it */
if ((SHORT)left_edge >= 0 && (SHORT)top_edge >= 0 && width && height &&
left_edge < (inner_left + inner_width) && top_edge < (inner_top +
inner_height)) {
if (left_edge < inner_left) {
left_edge = inner_left;
} else {
left_edge += inner_left;
}
if (top_edge < inner_top) {
top_edge = inner_top;
} else {
top_edge += inner_top;
}
if ((SHORT)width <= 0 || (left_edge + width) > (inner_left +
inner_width)) {
width = inner_left + inner_width - left_edge;
}
if ((SHORT)height <= 0 || (top_edge + height) > (inner_top +
inner_height)) {
height = inner_top + inner_height - top_edge;
}
if (flags & RENDER_INFO_FLAG_BACK_FILL) {
back_pen = ri->ri_BackPen;
} else {
back_pen = 0;
}
SetDrMd(rp, (LONG)JAM1);
SetAPen(rp, (LONG)back_pen);
RectFill(rp, (LONG)left_edge, (LONG)top_edge, (LONG)(left_edge +
width - 1), (LONG)(top_edge + height - 1));
}
}